﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RGeos.Basic;

namespace RGeos.Framework.OTL
{
    public interface ISag
    {
        /// <summary>
        /// 传入档距
        /// </summary>
        double L { get; set; }
        /// <summary>
        /// 传入挂点的高差，
        /// </summary>
        double h { get; set; }
        /// <summary>
        /// 导线K值
        /// </summary>
        double K { get; set; }
        /// <summary>
        /// 计算任意一点弧垂
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        double fx(double x);
        /// <summary>
        /// 最大弧锤
        /// </summary>
        /// <returns></returns>
        double fm();
    }
    public abstract class Sag : ISag
    {
        protected double m_a0;
        public double a0
        {
            get { return m_a0; }
        }
        protected double m_r;
        public double r
        {
            get { return m_r; }
        }
        protected double m_k;
        public double K
        {
            get { return this.m_k; }
            set { this.m_k = value; }
        }
        public double L { get; set; }
        public double h { get; set; }
        protected double InternalK
        {
            get { return 8 * Math.Pow(10, -5) * m_k; }
        }
        public Sag()
        {
        }
        public Sag(double k)
        {
            this.m_k = k;
        }
        public Sag(double a0, double r)
        {
            this.m_a0 = a0;
            this.m_r = r;
            this.m_k = Convert2K(a0, r);
        }
        public static double Convert2K(double a0, double r)
        {
            return r * Math.Pow(10, 5) / (8 * a0);
        }
        #region ISag 成员

        public virtual double fx(double x)
        {
            throw new NotImplementedException();
        }

        public virtual double fm()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
    /// <summary>
    /// 斜抛物线
    /// </summary>
    public class Parabola : Sag
    {
        public Parabola()
            : base()
        {
        }
        public Parabola(double k)
            : base(k)
        {
        }
        public Parabola(double a0, double r)
            : base(a0, r)
        {
        }
        public override double fx(double x)
        {
            double c = Math.Sqrt(L * L + h * h);
            double cosB = L / c;
            double tempK = InternalK;
            double tempfx = tempK * x * (L - x) / (2 * cosB);
            return tempfx;
        }
        public override double fm()
        {
            double c = Math.Sqrt(L * L + h * h);
            double cosB = L / c;
            double tempK = InternalK;
            return tempK * L * L / (8 * cosB);
        }
    }
    /// <summary>
    /// 悬链线
    /// </summary>
    public class Catenary : Sag
    {
        public Catenary()
            : base()
        {
        }
        public Catenary(double k)
            : base(k)
        {
        }
        public Catenary(double a0, double r)
            : base(a0, r)
        {
        }

        public override double fx(double x)
        {
            double tempK = InternalK;
            double loa = this.Loa();
            double tanB = h / L;
            double part0 = x * tanB;
            double part1 = 2 / tempK;
            double part2 = MathEx.sh(tempK * (2 * loa - x) / 2) * MathEx.sh(tempK * x / 2);
            return part0 + part1 * part2;
        }
        public double fx2(double x)
        {
            double tanB = h / L;
            double loatt = this.Loa();
            double loa = this.Loa(this.a0, r, h, L);
            return this.fx(x, tanB, a0, loa, loa);
        }
        public override double fm()
        {
            return base.fm();
        }
        public double Loa()
        {
            double tempK = InternalK;
            double part0 = 1 / tempK;
            double part1 = h * tempK / 2;
            double part2 = MathEx.sh(tempK * L / 2);
            double loa = 0.5 - part0 * MathEx.arsh(part1 / part2);
            return loa;
        }
        public double Lob()
        {
            double tempK = InternalK;
            double loa = 0.5 + (1 / tempK) * (MathEx.arsh((h * tempK / 2) / MathEx.sh(tempK * L / 2)));
            return loa;
        }

        private double fx(double x, double tanB, double a0, double r, double Loa)
        {
            double part0 = x * tanB;
            double part1 = 2 * a0 / r;
            double part2 = MathEx.sh(r * (2 * Loa - x) / (2 * a0)) * MathEx.sh(r * x / (2 * a0));
            return part0 + part1 * part2;
        }

        private double Loa(double a0, double r, double h, double l)
        {
            double loa = 0.5 * l - (a0 / r) * ((MathEx.arsh((r * h) / (2 * a0 * MathEx.sh((r * l) / (2 * a0))))));
            return loa;
            //double aaa = 0.5 * l - (a0 / r) * Math.Tan(h / l);
            //return aaa;
        }

    }
}
